//package gameConf
package gameConfData

import (
	"fmt"
	"github.com/TarsCloud/TarsGo/tars"
	"github.com/pkg/errors"
	"golang.org/x/net/context"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
	"reflect"
	"strings"
	"sync"
	"xxgame.com/CommApp/Util/littleFunc"
	"xxgame.com/TarsRelease/goProtocol/commTars"
)

// 存储游戏数据
type GameConfData struct {
	RwLockData map[string]*sync.RWMutex		// 不同配置表的读写锁
	GameData map[string]interface{}			// 这里 interface{} 相当于 map[int]interface{}
	ReLoadInfo map[string][]interface{}		// entityName 映射 [entity, []entity] (用于Load数据库的信息)
}

var gameConf *GameConfData

// 启动进程定义加载游戏数据配置
// 参数dbHandle：操作远程db句柄
// 参数reLoad: 是否重新加载对应配置表
// 参数n不定参：格式：[entity1, []entity1{}, entity2, []entity2{}, ...]（entityN与[]entityN{}必须配套传入）
// 【备注】：如果配置被多个服公用，建议配置对象定义文件摆到 Util/global/globalGameConf, 包名为 globalGameConf
func LoadGameConfV1(dbHandle *gorm.DB, reLoad bool, entitys ...interface{}) error {
	if nil == gameConf {
		gameConf = &GameConfData{
			RwLockData: map[string]*sync.RWMutex{},
			GameData: map[string]interface{}{},
		}
	}
	gameData := gameConf.GameData
	gameConfDao := New(dbHandle)
	for i := 0; i < len(entitys); i += 2 {
		listEntity, entityName, err := gameConfDao.FindByEntity(entitys[i], entitys[i+1])
		if nil != err || nil == listEntity {
			continue
		}
		rwLock, ok := gameConf.RwLockData[entityName]
		if !ok {
			rwLock = new(sync.RWMutex)
			gameConf.RwLockData[entityName] = rwLock
		}
		rwLock.Lock() 	// 加上写锁
		if reLoad {
			if _, ok := gameData[entityName]; ok {
				delete(gameData, entityName)
				tars.TLOG.Infof("LoadGameConf|清理配置成功|%s", entityName)
			}
		}
		mapConfCtn, ok := gameData[entityName].(map[int]interface{})
		if !ok {
			mapConfCtn = make(map[int]interface{})
			gameData[entityName] = mapConfCtn
		}
		for dbId, _ := range listEntity {
			dbEntity := listEntity[dbId]
			data := reflect.ValueOf(dbEntity)
			if 0 >= data.NumField() { // 空实例，则不参与索引建立
				continue
			}
			idx, mapData, sKey := MakeNextKeyValue2(mapConfCtn, 0, dbEntity, entityName)
			if _, ok2 := mapData[idx]; ok2 {
				panic(fmt.Sprintf("【MYSQL游戏配置数据错误】：配置表:%s, 字段:%s，Id:%d重复，"+
					"定位重复行ID：%+v", entityName, sKey, idx, data.FieldByName(entityName+"ID").Interface()))
			}
			mapData[idx] = dbEntity
		}
		rwLock.Unlock() // 释放写锁
		tars.TLOG.Infof("LoadGameConf|加载配置成功|%s", entityName)
	}
	return nil
}

// 【升级版本：key支持int和sting类型】
// 启动进程定义加载游戏数据配置
// 参数dbHandle：操作远程db句柄
// 参数reLoad: 是否重新加载对应配置表
// 参数n不定参：格式：[entity1, []entity1{}, entity2, []entity2{}, ...]（entityN与[]entityN{}必须配套传入）
// 【备注】：如果配置被多个服公用，建议配置对象定义文件摆到 Util/global/globalGameConf, 包名为 globalGameConf
func LoadGameConfV2(dbHandle *gorm.DB, reLoad bool, entitys ...interface{}) error {
	if nil == gameConf {
		gameConf = &GameConfData{
			RwLockData: map[string]*sync.RWMutex{},
			GameData: map[string]interface{}{},
		}
	}
	gameData := gameConf.GameData
	gameConfDao := New(dbHandle)
	for i := 0; i < len(entitys); i += 2 {
		listEntity, entityName, err := gameConfDao.FindByEntity(entitys[i], entitys[i+1])
		if nil != err || nil == listEntity {
			continue
		}
		rwLock, ok := gameConf.RwLockData[entityName]
		if !ok {
			rwLock = new(sync.RWMutex)
			gameConf.RwLockData[entityName] = rwLock
		}
		rwLock.Lock() 	// 加上写锁
		if reLoad {
			if _, ok := gameData[entityName]; ok {
				delete(gameData, entityName)
				tars.TLOG.Infof("LoadGameConf|清理配置成功|%s", entityName)
			}
		} else {
			// 首次加载数据
			gameConf.ReLoadInfo[entityName] = []interface{}{entitys[i], entitys[i+1]}
		}
		mapConfCtn, ok := gameData[entityName].(map[interface{}]interface{})
		if !ok {
			mapConfCtn = make(map[interface{}]interface{})
			gameData[entityName] = mapConfCtn
		}
		for dbId, _ := range listEntity {
			dbEntity := listEntity[dbId]
			data := reflect.ValueOf(dbEntity)
			if 0 >= data.NumField() { // 空实例，则不参与索引建立
				continue
			}
			idx, mapData, sKey := MakeNextKeyValueComm(mapConfCtn, 0, dbEntity, entityName)
			if _, ok2 := mapData[idx]; ok2 {
				panic(fmt.Sprintf("【MYSQL游戏配置数据错误】：配置表:%s, 字段:%s，Id:%d重复",
					entityName, sKey, idx))
			}
			mapData[idx] = dbEntity
		}
		rwLock.Unlock() // 释放写锁
		tars.TLOG.Infof("LoadGameConf|加载配置成功|%s", entityName)
	}
	return nil
}

// 【升级版本：key支持int和sting类型】(todo: 用LoadSingleConf重构该函数)
// 启动进程定义加载游戏数据配置
// 参数dbHandle：操作远程db句柄
// 参数reLoad: 是否重新加载对应配置表
// 参数n不定参：格式：[entity1, []entity1{}, entity2, []entity2{}, ...]（entityN与[]entityN{}必须配套传入）
// 【备注】：如果配置被多个服公用，建议配置对象定义文件摆到 Util/global/globalGameConf, 包名为 globalGameConf
func LoadGameConf(dbHandle *gorm.DB, entitys ...interface{}) error {
	if nil == gameConf { // 初始化 gameConf 全局变量
		gameConf = &GameConfData{
			RwLockData: map[string]*sync.RWMutex{},
			GameData: map[string]interface{}{},
			ReLoadInfo: map[string][]interface{}{},
		}
	}
	gameConfDao := New(dbHandle)
	for i := 0; i < len(entitys); i += 2 {
		err, entityName := LoadSingleConf(gameConfDao, entitys[i], entitys[i+1])
		if _, ok := gameConf.ReLoadInfo[entityName]; !ok { // 首次加载会记录entity相关信息
			if "" != entityName {
				gameConf.ReLoadInfo[entityName] = []interface{}{entitys[i], entitys[i+1]}
			}
		}
		if nil != err { // 告知前端重新加载是否成功还是失败
			extMsg := fmt.Sprintf("%+v", err.Error())
			tars.TLOG.Errorf("LoadGameConf|加载配置错误|%+v|%+v", entityName, extMsg)
		}
	}
	return nil
}

// 加载单个配置
func LoadSingleConf(gameConfDao *CommGameConfDao, entity interface{}, entityList interface{}) (error, string) {
	listEntity, entityName, err := gameConfDao.FindByEntity(entity, entityList)
	if nil != err {
		return err, entityName
	}
	if nil == listEntity {
		return errors.New("nil == listEntity"), entityName
	}
	rwLock, ok := gameConf.RwLockData[entityName]
	if !ok {
		rwLock = new(sync.RWMutex)
		gameConf.RwLockData[entityName] = rwLock
	}
	rwLock.Lock() 	// 加上写锁
	gameData := gameConf.GameData
	if _, ok := gameData[entityName]; ok {
		delete(gameData, entityName)
		tars.TLOG.Infof("LoadSingleConf|清理配置成功|%s", entityName)
	}
	mapConfCtn, ok := gameData[entityName].(map[interface{}]interface{})
	if !ok {
		mapConfCtn = make(map[interface{}]interface{})
		gameData[entityName] = mapConfCtn
	}
	for dbId, _ := range listEntity {
		dbEntity := listEntity[dbId]
		data := reflect.ValueOf(dbEntity)
		if 0 >= data.NumField() { // 空实例，则不参与索引建立
			continue
		}
		idx, mapData, sKey := MakeNextKeyValueComm(mapConfCtn, 0, dbEntity, entityName)
		if _, ok2 := mapData[idx]; ok2 {
			panic(fmt.Sprintf("【MYSQL游戏配置数据错误】：配置表:%s, 字段:%s，Id:%d重复，" +
				"定位重复行ID：%+v", entityName, sKey, idx, data.FieldByName(entityName+"ID").Interface()))
		}
		mapData[idx] = dbEntity
	}
	rwLock.Unlock() // 释放写锁
	tars.TLOG.Infof("LoadSingleConf|加载配置成功|%s", entityName)
	return nil, entityName
}

// 重新加载配置
func ReLoadGameConf(tarsCtx context.Context, dbHandle *gorm.DB, entityName string) bool {
	if nil == gameConf {
		extMsg := fmt.Sprintf("nil == gameConf")
		tars.TLOG.Errorf("ReLoadGameConf|重新加载配置错误|%+v|%+v", entityName, extMsg)
		littleFunc.SendMsg2Client(tarsCtx, &commTars.NotifyDebugMsg{NotifyMsg:extMsg})
		return false
	}
	gameConfDao := New(dbHandle)
	if "" == entityName {
		for _, reLoadInfo := range gameConf.ReLoadInfo {
			err, entityName2 := LoadSingleConf(gameConfDao, reLoadInfo[0], reLoadInfo[1])
			if nil != err { // 告知前端重新加载是否成功还是失败
				extMsg := fmt.Sprintf("%+v", err.Error())
				tars.TLOG.Errorf("ReLoadGameConf|重新加载配置错误|%+v|%+v", entityName2, extMsg)
				littleFunc.SendMsg2Client(tarsCtx, &commTars.NotifyDebugMsg{NotifyMsg:extMsg})
			} else {
				extMsg := fmt.Sprintf("ReLoadGameConf|重新加载配置成功|%+v", entityName2)
				littleFunc.SendMsg2Client(tarsCtx, &commTars.NotifyDebugMsg{NotifyMsg:extMsg})
			}
		}
		return true
	} else {
		if reLoadInfo, ok := gameConf.ReLoadInfo[entityName]; ok {
			err, _ := LoadSingleConf(gameConfDao, reLoadInfo[0], reLoadInfo[1])
			if nil != err { // 告知前端重新加载是否成功还是失败
				extMsg := fmt.Sprintf("%+v", err.Error())
				tars.TLOG.Errorf("ReLoadGameConf|重新加载配置错误|%+v|%+v", entityName, extMsg)
				littleFunc.SendMsg2Client(tarsCtx, &commTars.NotifyDebugMsg{NotifyMsg:extMsg})
				return false
			} else {
				extMsg := fmt.Sprintf("ReLoadGameConf|重新加载配置成功|%+v", entityName)
				littleFunc.SendMsg2Client(tarsCtx, &commTars.NotifyDebugMsg{NotifyMsg:extMsg})
				return true
			}
		} else {
			littleFunc.SendMsg2Client(tarsCtx, &commTars.NotifyDebugMsg{
				NotifyMsg: fmt.Sprintf("ReLoadGameConf|重新加载配置失败|请检查node参数是否正确")})
			return false
		}
	}
}

type CommGameConfDao struct {
	db *gorm.DB
}

func New(db *gorm.DB) *CommGameConfDao {
	return &CommGameConfDao{db:db}
}

func (this *CommGameConfDao) FindByEntity(entity interface{}, entityList interface{}) ([]interface{}, string, error) {
	// 参数校验
	if reflect.Slice != reflect.TypeOf(entityList).Kind() {
		return nil, "", errors.New("entityList is NOT slice, please check")
	}
	// 获取entity的tableName
	t := reflect.TypeOf(entity)
	v := reflect.New(t)
	m := v.MethodByName("TableName")
	ret := m.Call([]reflect.Value{})
	tblName := ret[0].Interface().(string)
	tars.TLOG.Infof("FindByEntity|获取配置表名|%s", tblName)
	// 获取格式化后的表名
	lTblName := strings.Split(tblName, "_")
	for i := 0; i < len(lTblName); i++ {
		lTblName[i] = fmt.Sprintf("%s%s",
			strings.ToUpper(lTblName[i][:1]), lTblName[i][1:])
	}
	entityName := strings.Join(lTblName[0:len(lTblName)-1], "")
	// 通过反射生成新的entityList
	t2 := reflect.TypeOf(entityList)
	v2 := reflect.New(t2)
	err := this.db.Where(v.Interface()).Find(v2.Interface()).Error
	if nil != err {
		if errors.Is(err, logger.ErrRecordNotFound) {
			return nil, entityName, nil
		}
		return nil, entityName, errors.WithStack(err)
	}
	result := []interface{}{}
	for i := 0; i < reflect.Indirect(v2).Len(); i++ {
		ele := reflect.Indirect(v2).Index(i)
		result = append(result, ele.Interface())
	}
	return result, entityName , nil
}

// 传入当前层级数据dataMap以及当前层idx、，返回当前需要设置dataMap以及需要设置的idx（读取Mysql版本）
func MakeNextKeyValue2(curLayerMap map[int]interface{}, curLayer int,
	dbEntity interface{}, structType string) (int, map[int]interface{}, string) {
	data := reflect.ValueOf(dbEntity)
	nextLayerId := data.FieldByName(fmt.Sprintf("ID%d",curLayer+1))
	if !nextLayerId.IsValid() { // 无下一层ID
		var sKey string
		if 0 == curLayer { // 层级为0，标识需要使用根id
			sKey = fmt.Sprintf("%sID", structType)
		} else if curLayer == 1 {
			// 配置了id1，但无id2，这属于非法配置情况，如果仅需一级id，使用id即可，无需增加id1字段
			panic(fmt.Sprintf("【配置非法】：配置表：%s，存在id%s，但不存在id%s",
				structType, curLayer, curLayer+1))
		} else if curLayer > 1 {
			sKey = fmt.Sprintf("ID%d", curLayer) // 让递归有终止条件
		}
		return int(data.FieldByName(sKey).Int()), curLayerMap, sKey
	} else { // 有下一层ID
		result := data.FieldByName(fmt.Sprintf("ID%d", curLayer+2)) // 试探是否有孙层索引
		if result.IsValid() {
			nextLayerId2 := int(nextLayerId.Int())
			nextLayerMap, ok2 := curLayerMap[nextLayerId2]
			if !ok2 {
				nextLayerMap = map[int]interface{}{}
				curLayerMap[nextLayerId2] = nextLayerMap
			}
			return MakeNextKeyValue2(nextLayerMap.(map[int]interface{}), curLayer+1, data.Interface(), structType)
		} else {
			return MakeNextKeyValue2(curLayerMap, curLayer+1, data.Interface(), structType)
		}
	}
}

// 增强版本（key是interface{}类型， 支持 int 和 string 类型）
// 传入当前层级数据dataMap以及当前层idx、，返回当前需要设置dataMap以及需要设置的idx（读取Mysql版本）
func MakeNextKeyValueComm(curLayerMap map[interface{}]interface{}, curLayer int,
	dbEntity interface{}, structType string) (interface{}, map[interface{}]interface{}, string) {
	data := reflect.ValueOf(dbEntity)
	nextLayerId := data.FieldByName(fmt.Sprintf("ID%d",curLayer+1))
	if !nextLayerId.IsValid() { // 无下一层ID
		var sKey string
		if 0 == curLayer { // 层级为0，标识需要使用根id
			sKey = fmt.Sprintf("%sID", structType)
		} else if curLayer == 1 {
			// 配置了id1，但无id2，这属于非法配置情况，如果仅需一级id，使用id即可，无需增加id1字段
			panic(fmt.Sprintf("【配置非法】：配置表：%s，存在id%s，但不存在id%s",
				structType, curLayer, curLayer+1))
		} else if curLayer > 1 {
			sKey = fmt.Sprintf("ID%d", curLayer) // 让递归有终止条件
		}
		// 同时兼容 int 和 string 作为 key
		switch data.FieldByName(sKey).Kind() {
		case reflect.String:
			return data.FieldByName(sKey).String(), curLayerMap, sKey
		default:
			return int(data.FieldByName(sKey).Int()), curLayerMap, sKey
		}
	} else { // 有下一层ID
		result := data.FieldByName(fmt.Sprintf("ID%d", curLayer+2)) // 试探是否有孙层索引
		if result.IsValid() {
			// 同时兼容 int 和 string 作为 key
			var nextLayerId2 interface{}
			switch nextLayerId.Kind() {
			case reflect.String:
				nextLayerId2 = nextLayerId.String()
			default:
				nextLayerId2 = int(nextLayerId.Int())
			}
			nextLayerMap, ok2 := curLayerMap[nextLayerId2]
			if !ok2 {
				nextLayerMap = map[interface{}]interface{}{}
				curLayerMap[nextLayerId2] = nextLayerMap
			}
			return MakeNextKeyValueComm(nextLayerMap.(map[interface{}]interface{}), curLayer+1, data.Interface(), structType)
		} else {
			return MakeNextKeyValueComm(curLayerMap, curLayer+1, data.Interface(), structType)
		}
	}
}

//// 启动进程首次调用
//func Init() {
//	ex, _ := os.Executable()
//	exePath := filepath.Dir(ex)
//	lExePath := strings.Split(exePath, "/")
//	// 可执行文件的上两层目录，也就是在CommApp目录下
//	exePath = strings.Join(lExePath[:len(lExePath)-2], "/")
//	if nil == gameConf {
//		gameConf = &GameConfData{
//			GameData: map[string]interface{}{},
//		}
//	}
//	// 加载可执行文件所在目录的json目录下的所有json文件
//	jsonPath := fmt.Sprintf("%s/gameJsonConf", exePath)
//	tars.TLOG.Infof(">>>>>>>> 【开始】尝试加载目录%s游戏数据", jsonPath)
//	filePathName, err := filepath.Glob(filepath.Join(jsonPath, "*"))
//	if nil != err {
//		panic(err)
//	}
//	for i := 0; i < len(filePathName); i++ {
//		tars.TLOG.Info(">>>> 【开始】加载游戏数据: %s", filePathName[i])
//		gameConf.load(filePathName[i])
//		tars.TLOG.Info("<<<< 【结束】加载游戏数据: %s", filePathName[i])
//	}
//}
//
//func Json2Map(jsonFileName string) map[string]interface{}{
//	json_bytes := littleFunc.ReadFile(jsonFileName)
//	var mapResult map[string]interface{}
//	err := json.Unmarshal([]byte(json_bytes), &mapResult)
//	if nil != err {
//		panic(err)
//	}
//	return mapResult
//}
//
//func Map2Struct(mapResult map[string]interface{}) map[int32]interface{} {
//	var confData interface{}
//	var structType string = fmt.Sprintf("%sConf", mapResult["ConfName"])
//	if structType!="EquipConf" {
//		return map[int32]interface{}{}
//	}
//	// 利用go反射目前只能做到这种程度的动态产出对象的方式（todo：还不灵活：需要写代码分支，后期看是否有其他更好办法优化）
//	switch structType {
//	case "GuideConf":
//		confData = gameConfEntity.GuideConf{}
//	case "PieceConf":
//		confData = gameConfEntity.PieceConf{}
//	case "BehaviorTreeConf":
//		confData = gameConfEntity.BehaviorTreeConf{}
//	case "ConstantConf":
//		confData = gameConfEntity.ConstantConf{}
//	case "DialogConf":
//		confData = gameConfEntity.DialogConf{}
//	case "DropConf":
//		confData = gameConfEntity.DropConf{}
//	case "EquipConf":
//		confData = gameConfEntity.EquipConf{}
//	case "FunctionConf":
//		confData = gameConfEntity.FunctionConf{}
//	case "HeroConf":
//		confData = gameConfEntity.HeroConf{}
//	case "HeroExpConf":
//		confData = gameConfEntity.HeroExpConf{}
//	case "ItemConf":
//		confData = gameConfEntity.ItemConf{}
//	case "MonsterConf":
//		confData = gameConfEntity.MonsterConf{}
//	case "NpcConf":
//		confData = gameConfEntity.NpcConf{}
//	case "ShopConf":
//		confData = gameConfEntity.ShopConf{}
//	case "SkillConf":
//		confData = gameConfEntity.SkillConf{}
//	case "EffectConf":
//		confData = gameConfEntity.EffectConf{}
//	case "BuffConf":
//		confData = gameConfEntity.BuffConf{}
//	case "StageControlConf":
//		confData = gameConfEntity.StageControlConf{}
//	case "RuleControlConf":
//		confData = gameConfEntity.RuleControlConf{}
//	case "MonsterParmConf":
//		confData = gameConfEntity.MonsterParmConf{}
//	case "BoxParmConf":
//		confData = gameConfEntity.BoxParmConf{}
//	case "ResParmConf":
//		confData = gameConfEntity.ResParmConf{}
//	case "ItemParmConf":
//		confData = gameConfEntity.ItemParmConf{}
//	case "StatsFixConf":
//		confData = gameConfEntity.StatsFixConf{}
//	case "TaskConf":
//		confData = gameConfEntity.TaskConf{}
//	case "TranslateConf":
//		confData = gameConfEntity.TranslateConf{}
//	case "EquipStrengthenConf":
//		confData = gameConfEntity.EquipStrengthenConf{}
//	default:
//		panic(fmt.Sprintf("需要在Map2Struct()函数中增加：case \"%s\" 处理分支", structType))
//	}
//
//	// 初始化在gameConf对应配置表的配置对象容器
//	gameData := gameConf.GameData
//	mapConfCtn, ok := gameData[structType].(map[int32]interface{})
//	if !ok {
//		mapConfCtn = make(map[int32]interface{})
//		gameData[structType] = mapConfCtn
//	}
//
//	// json数据转成项目所需要的结构体对象confObject(interface{})
//	targetMap := mapResult["ConfData"]
//	for k := range targetMap.(map[string]interface{}){
//		v := targetMap.(map[string]interface{})[k]
//		if 0 == len(v.(map[string]interface{})) { // 空map跳过
//			continue
//		}
//		confObjType := reflect.TypeOf(confData)
//		pConfObj := reflect.New(confObjType).Interface()
//		err := mapstructure.Decode(v, pConfObj)
//		if nil != err {
//			panic(err)
//		}
//		idx, mapData, sKey := MakeNextKeyValue(mapConfCtn, 0, v.(map[string]interface{}), structType)
//		if _, ok := mapData[idx]; ok {
//			panic(fmt.Sprintf("【配置错误】：配置表：%s, 字段：%s，Id：%d 重复", structType, sKey, idx))
//		}
//		mapData[idx] = pConfObj
//	}
//	return mapConfCtn
//}
//
//// 传入当前层级数据dataMap以及当前层idx、，返回当前需要设置dataMap以及需要设置的idx（读取json文件版本）
//func MakeNextKeyValue(curLayerMap map[int32]interface{}, curLayer int32,
//data map[string]interface{}, structType string) (int32, map[int32]interface{}, string) {
//	nextLayerId, ok := data[fmt.Sprintf("id%d", curLayer+1)]
//	if !ok { // 无下一层ID
//		var sKey string
//		if 0 == curLayer { // 层级为0，标识需要使用根id
//			sKey = "id"
//		} else if curLayer == 1 {
//			// 配置了id1，但是无id2，这属于非法配置情况，如果仅需一级id，使用id即可，无需增加id1字段
//			panic(fmt.Sprintf("【配置非法】：配置表：%s，存在id%s，但不存在id%s",
//				structType, curLayer, curLayer+1))
//		} else if curLayer > 1 {
//			sKey = fmt.Sprintf("id%d", curLayer) // 让递归有终止条件
//		}
//		return int32(data[sKey].(float64)), curLayerMap, sKey
//	} else { // 有下一层ID
//		_, ok3 := data[fmt.Sprintf("id%d", curLayer+2)] // 试探是否有孙层索引
//		if ok3 {
//			nextLayerId2 := int32(nextLayerId.(float64))
//			nextLayerMap, ok2 := curLayerMap[nextLayerId2]
//			if !ok2 {
//				nextLayerMap = map[int32]interface{}{}
//				curLayerMap[nextLayerId2] = nextLayerMap
//			}
//			return MakeNextKeyValue(nextLayerMap.(map[int32]interface{}), curLayer+1, data, structType)
//		} else {
//			return MakeNextKeyValue(curLayerMap, curLayer+1, data, structType)
//		}
//	}
//}
//
//// 从当前可执行文件根目录下的json目录内所有文件数据读取到内存
//func (this *GameConfData) load(confPathFileName string) {
//	// 通过文件名获取表名
//	confFileName := path.Base(confPathFileName)
//	fileExtName := path.Ext(confFileName)
//	extIdx := strings.Index(confFileName, fileExtName)
//	entityConfName := confFileName[:extIdx]
//
//	// 如果配置存在，则直接删除
//	gameData := gameConf.GameData
//	if _, ok := gameData[entityConfName]; ok {
//		delete(gameData, entityConfName)
//	}
//
//	// 读取json数据转map，再由map转对应结构的interface
//	mapResult := Json2Map(confPathFileName)
//	confData := Map2Struct(mapResult)
//	gameData[entityConfName] = confData
//}
//
//// 重新读取配置
//func (this *GameConfData) Reload(confNameList ...string) {
//	// 加载指定配置列表
//	for i := 0; i < len(confNameList); i++ {
//		this.load(confNameList[i])
//	}
//}